Shader "Studio/URP-YoFi/Character/Character-Face-div" 
{
	Properties
	{
//		_MainColorTint("Main Color Tint", color) = (1,1,1,1)
//		_DarkColorTint("Dark Color Tint", color) = (1,1,1,1)
//		_AmbientEffectFactor("Ambient Effect Factor", Range(0,1)) = 1
//		
//		_DarkColor("Dark Color", color) = (0.5,0.5,0.5,1)
//		_LambertMin ("Lambert Min", Range(0,1)) = 0
//		_LambertMax ("Lambert Max", Range(0,1)) = 1
//		_FresnelMin ("Fresnel Min", Range(0,1)) = 0
//		_FresnelMax ("Fresnel Max", Range(0,1)) = 1
//		[HDR]_FresnelColor("Fresnel Color", color) = (0.4,0.4,0.4,1)
//        _SupLightDir("SupLight Dir", Vector) = (-0.891, 0.454, 0.00,0)

		_MainTex ("MainTex", 2D) = "white" {}
		_DarkTex ("DarkTex", 2D) = "black" {}
		_FaceMaskTex("FaceMaskTex",2D) = "white"{}
		_DataTex ("DataTex", 2D) = "white" {}
		
		_SplitID("Split ID",Range(0,3)) = 0


		_OutlineWidth("_OutlineWidth", float) = 0.003
        _OutlineTint("_OutlineTint", color) = (0,0,0,1)
		
		_upDirWS("_upDirWS", Vector) = (0,1,0,0)
		_frontDirWS("_frontDirWS", Vector) = (0,0,-1,0)
		_rightDirWS("_rightDirWS", Vector) = (1,0,0,0)

        
        [Header(Shadow)]
        _ShadowColor("Shadow Color", color) = (0.0,0.0,0.0,0.5)
	}

	SubShader 
	{
		Tags
		{
			"RenderType" = "Opaque"
            "Queue" = "Geometry"
		}
		
		HLSLINCLUDE
		
		#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
		#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
		#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
		
		TEXTURE2D(_MainTex);
		TEXTURE2D(_DarkTex);
		TEXTURE2D(_DataTex);
		TEXTURE2D(_RMATex);
        TEXTURE2D (_NormalTex);
        TEXTURE2D (_FaceMaskTex);

		
		SAMPLER(sampler_RMATex);
        SAMPLER(sampler_NormalTex);

		SAMPLER(sampler_linear_repeat);
        SAMPLER(sampler_linear_clamp);

		float3 _upDirWS;
		float3 _frontDirWS;
		float3 _rightDirWS;



		CBUFFER_START(UnityPerMaterial)
		float _AmbientEffectFactor;

		float4 _DarkColor;
		float _LambertMin;
		float _LambertMax;
		float _FresnelMin;
		float _FresnelMax;
		float3 _SupLightDir;
		float3 _FresnelColor;

		float4 _NormalTex_ST;
        //float _BakedLightIntensity;
        float _NormalScale;
		float _Metallic;
		float _Roughness;
		
		float _SplitID;

		float _OutlineWidth;
        float3 _OutlineTint;
		CBUFFER_END
		        
		ENDHLSL

		Pass
		{
			HLSLPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			// #pragma multi_compile _ _MAIN_LIGHT_SHADOWS 
			// #pragma multi_compile _ _SHADOWS_SOFT
			#define _MAIN_LIGHT_SHADOWS true
			#define _SHADOWS_SOFT true
			// #pragma multi_compile _ LIGHTMAP_ON
			//#pragma multi_compile _ LIGHTMAP_SHADOW_MIXING
            //#pragma multi_compile _ SHADOWS_SHADOWMASK
			//#pragma multi_compile _ CALCULATE_BAKED_SHADOWS
			
			

			struct Attributes
			{
				float4 positionOS : POSITION;
				float3 normalOS     : NORMAL;
				float2 uv : TEXCOORD0;
				float2 uv2 : TEXCOORD1;
                float4 tangentOS : TANGENT;

			};

			struct Varyings
			{
				float4 positionHCS : SV_POSITION;
				float2 uv : TEXCOORD0;
				float2 uv2 : TEXCOORD1;
				float3 positionWS : TEXCOORD2;
				float3 normalWS  : TEXCOORD3;
                float3 tangentWS :TEXCOORD4;
                float3 BtangentWS : TEXCOORD5;
                float4 screenPos : TEXCOORD6;
				float3 frontDirWS : TEXCOORD7;
				float3 rightDirWS : TEXCOORD8;
				float3 upDirWS : TEXCOORD9;

			};

			Varyings vert (Attributes IN)
			{
				Varyings OUT;
				OUT.uv = IN.uv;
				OUT.uv2 = IN.uv2;
				OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);
				OUT.positionWS = TransformObjectToWorld(IN.positionOS.xyz);
                OUT.normalWS = TransformObjectToWorldNormal(IN.normalOS).xyz;
                OUT.tangentWS = TransformObjectToWorldDir(IN.tangentOS.xyz);
                OUT.BtangentWS = cross(OUT.normalWS.xyz,OUT.tangentWS.xyz) * IN.tangentOS.w * unity_WorldTransformParams.w;

				OUT.screenPos = ComputeScreenPos(OUT.positionHCS);
				OUT.frontDirWS = TransformObjectToWorldDir(float3(0,-1,0));
				OUT.rightDirWS = TransformObjectToWorldDir(float3(1,0,0));
				OUT.upDirWS = TransformObjectToWorldDir(float3(0,0,1));
				
				return OUT;
			}

            float3 DT_PS_OVERLAY(float3 _layer0, float3 _layer1)
            {
                const float3 layer0 = _layer0.rgb;// * _layer0.a;
                const float3 layer1 = _layer1.rgb;// * _layer1.a;
                // 预先计算 layer0 和 layer1 的最大值，减少重复计算
                const float layer0Max = max(layer0.r, max(layer0.g, layer0.b));
                // 计算步进值，判断 layer0 的最大值是否大于 0.5
                const float stepValue = step(0.5, layer0Max);
                float3 twoLayer0Layer1 = 2.0 * layer0 * layer1;
                float3 oneMinusLayer0 = 1.0 - layer0;
                float3 oneMinusLayer1 = 1.0 - layer1;
                float3 oneMinusTwoOneMinusLayer0OneMinusLayer1 = 1.0 - 2.0 * oneMinusLayer0 * oneMinusLayer1;
                // 使用 lerp 函数进行插值计算
                return lerp(twoLayer0Layer1, oneMinusTwoOneMinusLayer0OneMinusLayer1, stepValue);
            }

            float3 GetSDFDark(half2 uv)
            {  
                Light mainLight =  GetMainLight() ;//获取主光源

                float3 upDirWS = SafeNormalize(_upDirWS);
                float3 frontDirWS = SafeNormalize(_frontDirWS  );
				float3 rightDirWS = SafeNormalize(_rightDirWS  ); 


                float3 lightDirWS = (mainLight.direction)  ;
                
                float3 lightDirWSfull = normalize(lightDirWS - dot(lightDirWS, upDirWS) * upDirWS); // 做一次投影
                // float3 lightDirWSfull = SafeNormalize(lightDirWS);
                lightDirWS.y = 0;
                float3 lightDirH = SafeNormalize(lightDirWS);

                float threshold = 1.0 -  (dot(lightDirWSfull, frontDirWS) * 0.5 + 0.5);
                float filpU = sign(dot(lightDirH, -rightDirWS));
                half4 SDF = SAMPLE_TEXTURE2D(_FaceMaskTex, sampler_linear_repeat, uv * float2(filpU, 1));
                // half4 SDFR = SAMPLE_TEXTURE2D(_FaceMaskTex, sampler_linear_repeat, uv * float2(1, 1));
                // half4 SDFL = SAMPLE_TEXTURE2D(_FaceMaskTex, sampler_linear_repeat, uv * float2(-1, 1));

                // float ddd = dot(lightDirH, -rightDirWS) * 0.5 + 0.5;
                // ddd = saturate(ddd * 2.0);


                // SDF = lerp(SDFL,SDFR, ddd );
                float faceShadow = smoothstep(threshold - 0.01 , threshold + 0.01, SDF.r);
 

                return 1.0 - faceShadow; 
 
            }

			half4 frag (Varyings IN) : SV_Target
			{
				float3 positionWS = IN.positionWS; 
                float3 normalWS = SafeNormalize(IN.normalWS);

				float id = round(_SplitID);
				float columnRef = 2.0f;
				float rowRef = 2.0f;
				float row = floor( id / columnRef);
				float column = fmod(id , rowRef);
				
				float2 splitedUV = IN.uv.xy / float2(columnRef,rowRef) + float2(column,row) / float2(columnRef,rowRef);
			
				
				half4 mainTex = SAMPLE_TEXTURE2D(_MainTex, sampler_linear_repeat, splitedUV);
				half4 darkTex = SAMPLE_TEXTURE2D(_DarkTex, sampler_linear_repeat, splitedUV);
				half4 dataTex = SAMPLE_TEXTURE2D(_DataTex, sampler_linear_repeat, IN.uv);

				half4 faceMaskTex = SAMPLE_TEXTURE2D(_FaceMaskTex, sampler_linear_repeat, IN.uv);
                half3 mainColor = mainTex.rgb;
                
                             
                Light mainLight =  GetMainLight();//获取主光源 
                float lambert = dot(normalWS,mainLight.direction) * 0.5 + 0.5; 
				float ramp = smoothstep(  0.48, 0.5 ,saturate(lambert * mainLight.shadowAttenuation) );
				 
				float mainLightShadow = 1;
				float3 lightDirWS = mainLight.direction; 


                float sdfShadow = GetSDFDark(IN.uv).x;
				float mixShadow =lerp(sdfShadow,1.0 - ramp, faceMaskTex.g);
				float3 finalColor = lerp(darkTex.rgb, mainTex.rgb, (1.0 - mixShadow) * dataTex.r );
				return half4(finalColor,1.0);
			}
			ENDHLSL 
		}

		Pass
        {
            Name "Outline"
            Tags { "LightMode" = "OutlinePass" }
            Cull Front
            ZTest On
            ZWrite On

            HLSLPROGRAM

            #pragma vertex vert
            #pragma fragment frag

         
            struct Attributes
            {
                float4 color : COLOR;
                float2 uv0 : TEXCOORD0;
                float4 vertex : POSITION;
                float4 normal : NORMAL;
                float4 tangent : TANGENT;
            }; 

            struct Varyings
            {
                float4 positionHCS : SV_POSITION;
                float2 uv : TEXCOORD0;
            	float3 positionWS : TEXCOORD1;
            	float3 normalWS : TEXCOORD2;
            };

            Varyings vert(Attributes v)
            {
                Varyings OUT;

                float4 scaledScreenParams = GetScaledScreenParams();
                float ScaleX = abs(scaledScreenParams.x / scaledScreenParams.y);

                OUT.positionHCS = TransformObjectToHClip(v.vertex.xyz);
                OUT.positionWS = TransformObjectToWorld(v.vertex.xyz);

                float3 tangentOS = v.tangent.xyz;
                float3 normalOS = v.normal.xyz;
                float3 biTangentOS = cross(normalOS, tangentOS) * v.tangent.w * GetOddNegativeScale();

                float3 smoothNormalTS = v.color.rgb * 2 - 1;
                float3x3 TBN_TSOS= float3x3(tangentOS, biTangentOS, normalOS);

                float3 smoothNormalOS = mul(smoothNormalTS, TBN_TSOS);
                smoothNormalOS = SafeNormalize(smoothNormalOS);
                normalOS = smoothNormalOS;

                _OutlineWidth *= v.color.a;

                OUT.normalWS = TransformObjectToWorldNormal(normalOS);
                float3 normalCS = TransformWorldToHClipDir(OUT.normalWS);
                float2 extend = normalize(normalCS).xy * (_OutlineWidth*0.01); 
                extend.x /= ScaleX;


                //裁剪空间描边，可以使得相机远近描边宽度一致，和屏幕空间等宽边缘光思路一致
            	//_OutlineClampScale = 1 
                float ctrl = clamp(1/(OUT.positionHCS.w + 1),0,1);
                OUT.positionHCS.xy += extend * OUT.positionHCS.w * ctrl;
            	//OUT.positionHCS.xy += min(1.0 , OUT.positionHCS.w) * extend.xy;

                OUT.uv = v.uv0;
                return OUT;
            }
            
            float4 frag (Varyings IN) : SV_Target
            {
                half4 darkTex = SAMPLE_TEXTURE2D(_DarkTex,sampler_linear_repeat,IN.uv);
                return half4(_OutlineTint.xyz * darkTex.xyz , 1);
            }            
            ENDHLSL
        }        
        USEPASS "Studio/URP-YoFi/Character/Character-Toon-div/MeshShadow"
		Pass
        {
            Name "DepthOnly"
            Tags{"LightMode" = "DepthOnly"}

            ZWrite On
            ColorMask r
            Cull Back

            HLSLPROGRAM
            #pragma only_renderers gles gles3 glcore d3d11
            #pragma target 2.0
            #pragma vertex DepthOnlyVertex
            #pragma fragment DepthOnlyFragment
            // Material Keywords
            //#pragma shader_feature_local_fragment _ALPHATEST_ON
            //#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
            // GPU Instancing
            #pragma multi_compile_instancing
            #pragma shader_feature_local _ _ALPHATEST

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

            struct Attributes
            {
                float4 position     : POSITION;
                float2 texcoord     : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct Varyings
            {
                float4 positionCS   : SV_POSITION;
                float2 uv           : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
                UNITY_VERTEX_OUTPUT_STEREO
            };

            Varyings DepthOnlyVertex(Attributes input)
            {
                Varyings output = (Varyings)0;
                UNITY_SETUP_INSTANCE_ID(input);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
                //output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap);
                output.uv = input.texcoord;

                output.positionCS = TransformObjectToHClip(input.position.xyz);
                return output;
            }

            half4 DepthOnlyFragment(Varyings input) : SV_TARGET
            {
                UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
                // Alpha(SampleAlbedoAlpha(input.uv, TEXTURE2D_ARGS(_BaseMap, sampler_BaseMap)).a, _BaseColor, _Cutoff);
            #if defined(_ALPHATEST)
                float transTex = SAMPLE_TEXTURE2D(_TransTex, sampler_TransTex, input.uv).r - _Transparent;
                clip(transTex);
            #endif

                return half4(0,0,0,1);
            }
            ENDHLSL
        }

        Pass
        {
            Name "DepthNormals"
            Tags{"LightMode" = "DepthNormals"}

            ZWrite On
            Cull Back

            HLSLPROGRAM
            #pragma only_renderers gles gles3 glcore d3d11
            #pragma target 2.0
            #pragma vertex DepthNormalsVertex
            #pragma fragment DepthNormalsFragment
            // Material Keywords
            //#pragma shader_feature_local _NORMALMAP
            //#pragma shader_feature_local _PARALLAXMAP
            //#pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED
            //#pragma shader_feature_local_fragment _ALPHATEST_ON
            //#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
            // GPU Instancing
            #pragma multi_compile_instancing

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            // #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
            // #include "Packages/com.unity.render-pipelines.universal/Shaders/LitDepthNormalsPass.hlsl"

            struct Attributes
            {
                float4 position     : POSITION;
                half3 normalOS      : NORMAL;
                // float2 texcoord     : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct Varyings
            {
                float4 positionCS   : SV_POSITION;
                float3 positionWS   : TEXCOORD1;
                half3  normalWS     : TEXCOORD2;
                // float2 uv           : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
                UNITY_VERTEX_OUTPUT_STEREO
            };

            Varyings DepthNormalsVertex(Attributes input)
            {
                Varyings output = (Varyings)0;
                UNITY_SETUP_INSTANCE_ID(input);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
                // output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap);
                output.positionCS = TransformObjectToHClip(input.position.xyz);
                output.normalWS = TransformObjectToWorldNormal(input.normalOS);
                return output;
            }

            half4 DepthNormalsFragment(Varyings input) : SV_TARGET
            {
                UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
                // Alpha(SampleAlbedoAlpha(input.uv, TEXTURE2D_ARGS(_BaseMap, sampler_BaseMap)).a, _BaseColor, _Cutoff);
                return half4(input.normalWS, 1);
            }
            ENDHLSL
        }

        Pass
        {
            Name "Meta"
            Tags{"LightMode" = "Meta"}

            Cull Off

            HLSLPROGRAM
            #pragma exclude_renderers gles gles3 glcore
            #pragma target 4.5

            #pragma vertex UniversalVertexMeta
            #pragma fragment UniversalFragmentMetaLit

            #pragma shader_feature EDITOR_VISUALIZATION
            #pragma shader_feature_local_fragment _SPECULAR_SETUP
            #pragma shader_feature_local_fragment _EMISSION
            #pragma shader_feature_local_fragment _METALLICSPECGLOSSMAP
            //#pragma shader_feature_local_fragment _ALPHATEST_ON
            //#pragma shader_feature_local_fragment _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
            //#pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED

            #pragma shader_feature_local_fragment _SPECGLOSSMAP
            
			//#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
            
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/MetaInput.hlsl"
            

			struct Attributes
			{
			    float4 positionOS   : POSITION;
			    float3 normalOS     : NORMAL;
			    float2 uv0          : TEXCOORD0;
			    float2 uv1          : TEXCOORD1;
			    float2 uv2          : TEXCOORD2;
			    UNITY_VERTEX_INPUT_INSTANCE_ID
			};

			struct Varyings
			{
			    float4 positionCS   : SV_POSITION;
			    float2 uv           : TEXCOORD0;
			#ifdef EDITOR_VISUALIZATION
			    float2 VizUV        : TEXCOORD1;
			    float4 LightCoord   : TEXCOORD2;
			#endif
			};

			Varyings UniversalVertexMeta(Attributes input)
			{
			    Varyings output = (Varyings)0;
			    output.positionCS = UnityMetaVertexPosition(input.positionOS.xyz, input.uv1, input.uv2);
			    //output.uv = TRANSFORM_TEX(input.uv0, _BaseMap);
			    output.uv = input.uv0;
			#ifdef EDITOR_VISUALIZATION
			    UnityEditorVizData(input.positionOS.xyz, input.uv0, input.uv1, input.uv2, output.VizUV, output.LightCoord);
			#endif
			    return output;
			}

			half4 UniversalFragmentMeta(Varyings fragIn, MetaInput metaInput)
			{
			#ifdef EDITOR_VISUALIZATION
			    metaInput.VizUV = fragIn.VizUV;
			    metaInput.LightCoord = fragIn.LightCoord;
			#endif

			    return UnityMetaFragment(metaInput);
			}
            
            half4 UniversalFragmentMetaLit(Varyings input) : SV_Target
            {

            	half4 mainTex = SAMPLE_TEXTURE2D(_MainTex, sampler_linear_repeat, input.uv);    //颜色
				

                MetaInput metaInput;
                metaInput.Albedo = mainTex.rgb;
                metaInput.Emission = mainTex.rgb*mainTex.a;
                return UniversalFragmentMeta(input, metaInput);
            }
            
            
            ENDHLSL
        }

// 		Pass 
//         {
//             Name "ShadowCaster"
//             Tags{ "LightMode" = "ShadowCaster" }
//             Cull Back

//             HLSLPROGRAM
//             #pragma vertex vert
//             #pragma fragment frag


//             struct a2v {
//                 float4 vertex : POSITION;
//                 //float2 uv : TEXCOORD0;
//                 float3 normal : NORMAL;
//             };
//             struct v2f {
//                 float4 vertex : SV_POSITION;
//                 //float2 uv : TEXCOORD0;
//             };

//             v2f vert(a2v v)
//             {
//                 v2f o = (v2f)0;
//                 float3 worldPos = TransformObjectToWorld(v.vertex.xyz);
//                 half3 normalWS = TransformObjectToWorldNormal(v.normal);
//                 Light mainLight =  GetMainLight();//获取主光源

//                 worldPos = ApplyShadowBias(worldPos, normalWS, mainLight.direction);
//                 o.vertex = TransformWorldToHClip(worldPos);
//                 //o.uv = TRANSFORM_TEX(v.uv, _MainTex);
//                 return o;
//             }
//             real4 frag(v2f i) : SV_Target
//             {
// //#if _ALPHATEST_ON
// //                half4 col = tex2D(_MainTex, i.uv);
// //                clip(col.a - 0.001);
// //#endif
//                 return 0;
//             }
        //     ENDHLSL
        // }
	}
}